<?php
// +----------------------------------------------------------------------
// | Description: base controller no auth
// +----------------------------------------------------------------------
// | Author: orchief
// +----------------------------------------------------------------------

namespace app\client\controller;

use app\client\model\Member;
use app\client\model\SkuItem;
use app\common\controller\Common;
use EasyWeChat\Factory;
use SmsCode\SmsModel;
use think\image\Exception;
use think\Request;
use \Firebase\JWT\JWT;
use think\Db;

/**
 * Class Base
 * @package app\admin\controller
 */
class Base extends Common
{
    public function test()
    {

    }

    /**
     * 微信服务器推送
     *
     * @return void
     */
    public function wechatPush()
    {
        $config = [
            'app_id' => 'wx5876e5d51f69fbd9',
            // 'secret' => '9be0f0536ec0561d3731197729aa341e',
            'secret' => '9be0f0536ec0561d3731197729aa341e',
            'token'   => 'ceshi',          // Token

            // 指定 API 调用返回结果的类型：array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',

            'log' => [
                'level' => 'debug',
                'file' => './wechat2.log',
            ],
        ];

        $app = Factory::officialAccount($config);

        $app->server->push(function ($message) {
            
            switch ($message['MsgType']) {
                case 'event':
                    // 这里进行数据库操作
                    $data['OpenId'] = $message['FromUserName'];
                    $data['ReferUserId'] = $message['EventKey'];
                    file_put_contents('1.log', json_encode($data));
                    Db::table('shop_members_temp') -> insert($data);
                    file_put_contents('2.log', 'json_encode($data)');
                    return '欢迎';
                    break;
                // ... 其它消息
                default:
                    return '';
                    break;
            }

            // ...
        });

        $response = $app->server->serve();

        $response->send();
    }

    /**
     * sign up 用户注册
     *
     * @return void
     */
    public function signUp()
    {   //首先判断用户是否已经注册
        $this->checkPhone($this->param['CellPhone']);
        //使用助手函数validate方法验证balidate目录下面的base验证规则
        $validate = validate('base');
        //验证规则为必须填写
        $this->abort($validate->scene('signUp')->check($this->param), $validate->getError());
        //对验证码进行校验
        $this->checkCode();
        $Member = new Member();
        //将随机生成的用户名字符赋值给提交的用户
        $this->param['UserName'] = $this->getUniqueUserName();
        //uniqid函数以字符串的形式生成一个随机的ID
        $salt = uniqid();
        $this->param['PasswordSalt'] = $salt;
        $this->param['CreateDate'] = time();
        $this->param['Password'] = user_md5($this->param['Password'], $salt);
        $this->checkRes($Member->createData($this->param), '注册成功!', $Member->getError());

    }

    /**
     * login
     *
     * @return void
     */

       



    public function login()
    {
        $ErrorMsg = '登录失败!';
        $key = config('jwt.key'); // 签名秘钥
        $expire = config('jwt.expire'); // 俩小时失效
        $refresh = $expire + 60; // 令牌失效60秒之内可以重新获取

        $Member = new Member();
        $userInfo = $Member->where(['CellPhone' => $this->param['CellPhone']])->find();
         // $userInfo = $Member->where('CellPhone','=',$this->param['CellPhone'])->find();
        // 如果是微信端 则 存储用户openid
        // if ($this->param['OpenId']) {
        //     try {
        //         $Member->where(['Id' => $userInfo['Id']])->update(['OpenId' => $this->param['OpenId']]);

        //         // 检查该用户是否有推荐人 如果没有 则将临时表中数据取出 给该用户当推荐人
        //         if($userInfo['ReferUserId'] == 0){
        //             $tempData = Db::table('shop_members_temp') ->  where(['OpenId' => $this->param['OpenId']]) -> find();
        //             if(!$tempData){
        //                 $ErrorMsg = '请扫码绑定推荐人!';
        //                 $this -> abort(false, '121');
        //             }else{
        //                 if($userInfo['Id'] == $tempData['ReferUserId']){
        //                     $ErrorMsg = '请扫码绑定推荐人!';
        //                     $this -> abort(false, '121');
        //                 }
        //                 $Member ->where(['CellPhone' => $this->param['CellPhone']]) -> update(['ReferUserId' => $tempData['ReferUserId']]);
        //             }
        //         }

        //     } catch (\Exception $e) {
        //         $this->abort(false, $ErrorMsg);
        //     }
        // }
        //账号校验
        $this->abort($userInfo, '手机号不存在!');
        $this->abort($userInfo['Enabled'], '账户被冻结!');
        
        $data['UserId'] = $userInfo['Id'];
        $data['Password'] =
        $data['expireDate'] = time() + $expire; // 规定令牌失效时间
        $data['refreshDate'] = time() + $refresh; // 规定令牌失效之后可重新获取的时间

        $jwt = JWT::encode($data, $key);

        try {
            session('MemberInfo', $userInfo);
        } catch (\Exception $e) {
            $this->abort(false, $e->getMessage());
        }
        //密码校验
        $this->checkRes($userInfo['Password'] == \user_md5($this->param['Password'], $userInfo['PasswordSalt']), $jwt, '用户名或密码错误');
    }

    /**
     * get wechat openid
     *
     * @return void
     */
    public function wechatLogin()
    {
        // p(1);
        $config = [
            'app_id' => config('wechat.app_id'),
            'secret' => config('wechat.secret'),

            // 指定 API 调用返回结果的类型：array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',

            'oauth' => [
                'scopes' => ['snsapi_base'],
                'callback' => '/base/oauth_callback',
            ],

            'log' => [
                'level' => 'debug',
                'file' => __DIR__ . '/wechat.log',
            ],
        ];

        $app = Factory::officialAccount($config);
        $oauth = $app->oauth;

        $Member = new Member();
        $MemberInfo = $Member->get($this->param['UserId']);
        $oauth->redirect()->send();
    }

    /**
     * 授权回调
     *
     * @return void
     */
    public function oauth_callback()
    {
        // p(1);
        $config = [
            'app_id' => config('wechat.app_id'),
            'secret' => config('wechat.secret'),

            // 指定 API 调用返回结果的类型：array(default)/collection/object/raw/自定义类名
            'response_type' => 'array',

            'log' => [
                'level' => 'debug',
                'file' => __DIR__ . '/wechat.log',
            ],
        ];

        $app = Factory::officialAccount($config);
        $oauth = $app->oauth;

        // 获取 OAuth 授权结果用户信息
        $user = $oauth->user();
        header('Location: /wx/login?OpenId=' . $user['id']);
    }

    public function refreshToken()
    {
        $headers = Request::instance()->header();
        $this->abort($headers['authorization'], '缺少必要参数');
        $key = config('jwt.key'); // 签名秘钥

        $headers['authorization'] = $headers['authorization'];
        try {
            $decoded = JWT::decode($headers['authorization'], $key, array('HS256'));
        } catch (\Exception $e) {
            $this->abort(false, '鉴权失败');
        }

        $Member = new Member();

        $resArr = $this->object_to_array($decoded);

        $this->abort($resArr['refreshDate'] > time(), '令牌已过重新获取有效期, 请重新登录');

        $expire = config('jwt.expire'); // 俩小时失效
        $refresh = $expire + 60; // 令牌失效60秒之内可以重新获取

        $resArr['expireDate'] = time() + $expire;
        $resArr['refreshDate'] = time() + $refresh;
        try {
            $jwt = JWT::encode($resArr, $key);
        } catch (\Exception $e) {
            $this->abort(false, '获取失败');
        }

        $this->jsonData($jwt);
    }

    /**
     * reset pass by phoneNum
     *
     * @return void
     */
    public function resetPassByPhone()
    {
        $this->checkCode();
        $this->abort($this->param['NewPass'], '新密码不能为空!');
        $param['Password'] = $this->param['NewPass'];
        $Member = new Member();
        $MemberInfo = $Member->where(['CellPhone' => $this->param['CellPhone']])->find();
        $this->abort($MemberInfo, $Member->getError());
        $salt = $MemberInfo['PasswordSalt'];
        $param['Password'] = user_md5($param['Password'], $salt);
        // p($param);
        try {
            $res = $Member->where(['CellPhone' => $this->param['CellPhone']])->update($param);
        } catch (\Exception $e) {
            $this->checkRes($res, '重置成功!', $e->getMessage());
        }
        $this->jsonData('重置成功!');
    }

    /**
     * 注销
     *
     * @return void
     */
    public function logout()
    {
        try {
            session('MemberInfo', null);
        } catch (\Exception $e) {
            $this->abort(false, $e->getMessage());
        }
        $this->jsonData('退出成功!');
    }

    /**
     * Getting SMS authentication code
     * 获取短信验证码接口
     */
    public function SmsCode()
    {   
        //1:短信验证码没有过期，不用再次获取
        $queryTimes = 60; // Frequency default 60s

        $time = time() - session('SmsExpireDate');
       
        $this->abort($time >= $queryTimes, '您已获取验证码, 请' . ($queryTimes - $time) . '秒后重试');

        $SmsModel = new SmsModel();
        //2：手机号必须填写
        $this->abort(!empty($this->param['CellPhone']), '手机号不能为空');

        $res = $SmsModel->getCode($this->param['CellPhone']);

        $this->abort($res, $SmsModel->getError());

        // Failure time
        session('SmsExpireDate', time());
        //获取成功后页面的提示信息
        $this->checkRes($res, '获取成功', $SmsModel->getError());
    }

    /**
     * by skuitems get sku
     *
     * @return void
     */
    public function sku()
    {
        $model = new SkuItem();
        $data = $model->getSku($this->param);
        $this->jsonData($data, $model->getError());
    }

    /**
     * array to object
     *
     * @param object $obj Object
     * @return array
     */
    public function object_to_array($obj)
    {
        $obj = (array) $obj;
        foreach ($obj as $k => $v) {
            if (gettype($v) == 'resource') {
                return;
            }
            if (gettype($v) == 'object' || gettype($v) == 'array') {
                $obj[$k] = (array) object_to_array($v);
            }
        }

        return $obj;
    }

// ------------------------------------------------------------------
    // private
    // ------------------------------------------------------------------
    /**
     * check phone num if exist
     *
     * @return void
     */
    private function checkPhone($cellPhone)
    {
        $Member = new Member();
        //判断用户是否已经注册
        //若没有注册，调用abort方法没有提示，若已经注册了的话， 
        $this->abort(!($Member->where(['CellPhone' => $cellPhone])->count()), '账户已注册,请直接登录');
    }

    /**
     * check sms code
     * 验证码校验
     */
    protected function checkCode()
    {   
        
        //1：校验验证码是否填写
        //2：校验验证码是否过期
        //3：校验验证码是否正确
        $this->abort(!empty($this->param['code']), '请输入验证码');

        //定义验证码过期时间为300秒
        $MaxTimes = 60 * 5;
        $time = time() - session('SmsExpireDate');
        $this->abort($time < $MaxTimes, '您的验证码已失效, 请重新获取');
        //验证码跟手机号匹配
        $code = session('code');
        $phone = session('CellPhone');
        $this->abort($code == $this->param['code'] and ($phone == $this->param['CellPhone']), '验证码错误');
    }

    /**
     * get unique username
     * 随机生成(对时间戳进行进制转换.随机6位的字符串)
     * @return void
     */
    public function getUniqueUserName()
    {   
       
        $chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        $username = "";

        for ($i = 0; $i < 6; $i++) {
            $username .= $chars[mt_rand(0, strlen($chars))];
        }
        return strtoupper(base_convert(time() - 1420070400, 10, 36)) . $username;
    }
}
